package com.rapida.db;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.rapida.framwork.RapidaLog;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.TreeMap;

/**
 * Created by mm on 2015/1/19.
 */
public class SQLitePersistentObject {
	protected static Context mContext;
	protected static SQLiteHelper mHelper;
	private String TABLE_NAME;
	private HashMap<String, Class<?>> COLUMN = new HashMap<String, Class<?>>();
	private HashMap<String, Object> COLUMN_VALUE = new HashMap<String, Object>();

	public SQLitePersistentObject(Context context) {
		registerObjectOutlet(this);
		TABLE_NAME = this.getClass().getSimpleName();
		mContext = context;
		mHelper = new SQLiteHelper(context, TABLE_NAME, COLUMN);
	}

	public SQLitePersistentObject(Context context, Object classObj) {
		registerObjectOutlet(classObj);
		TABLE_NAME = classObj.getClass().getSimpleName();
		mContext = context;
		mHelper = new SQLiteHelper(context, TABLE_NAME, COLUMN);
	}

	public void registerObjectOutlet(Object classObj) {
		Field[] fields = classObj.getClass().getDeclaredFields();
		if (fields != null && fields.length > 0) {
			for (Field field : fields) {
				try {
					field.setAccessible(true);
					IDBOutlet outlet = field.getAnnotation(IDBOutlet.class);
					if (outlet != null) {
						String viewId = outlet.id();
						COLUMN.put(viewId, field.getType());
					}
				} catch (Exception e) {
					RapidaLog.e("registerDBColumn exception");
				}
			}
		}
	}

	private void getObjectOutlet(Object classObj) {
		Field[] fields = classObj.getClass().getDeclaredFields();
		if (fields != null && fields.length > 0) {
			for (Field field : fields) {
				try {
					field.setAccessible(true);
					IDBOutlet outlet = field.getAnnotation(IDBOutlet.class);
					if (outlet != null) {
						String viewId = outlet.id();
						COLUMN_VALUE.put(viewId, field.get(classObj));
					}
				} catch (Exception e) {
					RapidaLog.e("getDBColumn exception");
				}
			}
		}
	}

	public void save() {
		getObjectOutlet(this);
		if (canInsert()) {
			insert();
		} else {
			update();
		}
	}

	private boolean canInsert() {
		SQLiteDatabase db = mHelper.getReadableDatabase();
		Cursor c = null;
		try {
			c = db.rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE _index=?", new String[]{COLUMN_VALUE.get("_index").toString()});
			return !c.moveToFirst();
		} catch (Exception e) {
			RapidaLog.e("canInsert exception");
		} finally {
			if (c != null) {
				c.close();
			}
		}
		return true;
	}

	private void insert() {
		StringBuilder sql_key = new StringBuilder();
		StringBuilder sql_value = new StringBuilder();
		ArrayList<Object> objects = new ArrayList<Object>();
		sql_key.append("INSERT INTO " + TABLE_NAME);
		sql_key.append(" (");
		Iterator iterator = COLUMN_VALUE.entrySet().iterator();
		while (iterator.hasNext()) {
			TreeMap.Entry entry = (TreeMap.Entry) iterator.next();
			sql_key.append(entry.getKey());
			sql_key.append(",");
			sql_value.append("?");
			sql_value.append(",");
			objects.add(entry.getValue());
		}
		sql_key.deleteCharAt(sql_key.length() - 1);
		sql_key.append(") ");
		sql_key.append("VALUES (");
		sql_value.deleteCharAt(sql_value.length() - 1);
		sql_value.append(")");
		sql_key.append(sql_value);
		SQLiteDatabase db = mHelper.getWritableDatabase();
		try {
			db.execSQL(sql_key.toString(), objects.toArray());
		} catch (Exception e) {
			RapidaLog.e("insert exception");
		} finally {
			db.close();
		}
	}

	public void update() {
		StringBuilder sql_key = new StringBuilder();
		ArrayList<Object> objects = new ArrayList<Object>();
		sql_key.append("UPDATE " + TABLE_NAME + " SET ");
		Object index = COLUMN_VALUE.get("_index");
		COLUMN_VALUE.remove("_index");
		Iterator iterator = COLUMN_VALUE.entrySet().iterator();
		while (iterator.hasNext()) {
			TreeMap.Entry entry = (TreeMap.Entry) iterator.next();
			sql_key.append(entry.getKey());
			sql_key.append("=?");
			sql_key.append(",");
			objects.add(entry.getValue());
		}
		sql_key.deleteCharAt(sql_key.length() - 1);
		sql_key.append(" WHERE _index=?");
		objects.add(index);
		SQLiteDatabase db = mHelper.getWritableDatabase();
		try {
			db.execSQL(sql_key.toString(), objects.toArray());
		} catch (Exception e) {
			RapidaLog.e("update exception");
		} finally {
			db.close();
		}
	}
}
